/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc. 
 *  
 * SPDX-License-Identifier: Apache-2.0.
 * 
 * @Date: 2021-07-13 13:41:03
 * @LastEditTime: 2021-07-15 15:46:12
 * @Description:  This files is for 
 * 
 * @Modify History: 
 *  Ver   Who        Date         Changes
 * ----- ------     --------    --------------------------------------
 */
#ifndef BSP_DRIVERS_E2000_TIMER_HW_H
#define BSP_DRIVERS_E2000_TIMER_HW_H

#ifdef __cplusplus
extern "C"
{
#endif

#include "ft_io.h"
#include "ft_types.h"
#include "kernel.h"
#include "parameters.h"

/* register offset */
#define TIMER_CTRL_REG_OFFSET          (0x0)
#define TACHO_VALL_REG_OFFSET          (0x4)
#define TIMER_COMP_VALU_OFFSET         (0x8)
#define TIMER_COMP_VALL_OFFSET         (0x1c)
#define TIMER_CNT_VALU_OFFSET          (0x20)
#define TIMER_CNT_VALL_OFFSET          (0x24)
#define TIMER_INTR_MASK_OFFSET         (0x28)
#define TIMER_INTR_STATUS_OFFSET       (0x2c)
#define TACHO_OVER_LIM_OFFSET          (0x30)
#define TACHO_UNDER_LIM_OFFSET         (0x34)
#define TIMER_START_VAL_OFFSET         (0x38)

/* bit set */
/* timer ctrl */
#define TIMER_REG_TACHO_MODE_MASK         (0x3 << 0) //bit [1:0] RW
#define TIMER_REG_TACHO_MODE_TIMER        (0x0 << 0)
#define TIMER_REG_TACHO_MODE_TACHO        (0x1 << 0)
#define TIMER_REG_TACHO_MODE_CAPTURE      (0x2 << 0)

#define TIMER_REG_TACHO_RESET             (0x1 << 2) //in reset status

#define TIMER_REG_TACHO_FORCE_LOAD        (0x1 << 3) //force to update
#define TIMER_REG_TACHO_CAPTURE_ENABLE    (0x1 << 4) //enable input capture
#define TIMER_REG_TACHO_CAPTURE_CNT       (0x7f << 5) //in capture mode, cause intr when egde counting reach this val
#define TIMER_REG_TACHO_CAPTURE_CNT_SHIFT 5

#define TACHO_REG_ANTI_JITTER_MASK        (0x3 << 18) //anti jitter num = N + 1
#define TACHO_REG_ANTI_JITTER_SHIFT       18

#define TACHO_REG_MODE_MASK               (0x3 << 20) //select tacho input mode 
#define TACHO_REG_MODE_FALLING_EDGE       (0x0 << 20)
#define TACHO_REG_MODE_RISING_EDGE        (0x1 << 20)
#define TACHO_REG_MODE_DOUBLE_EDGE        (0x2 << 20)

#define TIMER_REG_CNT_RESTART             (0x1 << 22) //select timer cnt mode
#define TIMER_REG_CNT_FREERUN             (0x0 << 22)

#define TIMER_REG_CNT_SERIES_64BIT         (0x1 << 24) 
#define TIMER_REG_CNT_SERIES_32BIT         (0x0 << 24)

#define TIMER_REG_ENABLE                   (0x1 << 25) //enable timer count

#define TIMER_REG_CNT_CLR                  (0x1 << 26)
#define TIMER_REG_CNT_NOCLR                (0x0 << 26)

#define TIMER_REG_MODE_ONCE                (0x1 << 27) //one time timer
#define TIMER_REG_MODE_CYC                 (0x0 << 27) //cycle timer

#define TACHO_REG_CAP_IN_ENABLE            (0x1 << 31) //enable tacho capture input

/* tacho result */
#define TACHO_REG_RESU_MASK                GENMASK(30, 0) //bit [30:0], tacho result
#define TACHO_REG_RESU_ISVALID             (0x1 << 31) //tacho result is valid

/* tacho over */
#define TACHO_REG_OVER_MASK           GENMASK(30, 0)

/* tacho under */
#define TACHO_REG_UNDER_MASK          GENMASK(30, 0)

/* intr mask */
#define TACHO_OVER_INTR_EN            (0x1 << 0)
#define TACHO_UNDER_INTR_EN           (0x1 << 1)
#define TIMER_ROLLOVER_INTR_EN        (0x1 << 2)
#define TIMER_ONCECMP_INTR_EN         (0x1 << 3)
#define TIMER_CYCCMP_INTR_EN          (0x1 << 4)
#define TACHO_CAPTURE_INTR_EN         (0x1 << 5)

#define TIMER_ALL_INTR_EN           (TIMER_ROLLOVER_INTR_EN | TIMER_ONCECMP_INTR_EN | TIMER_CYCCMP_INTR_EN)

/* intr status */
#define TACHO_OVER_INTR_STATUS            (0x1 << 0)
#define TACHO_UNDER_INTR_STATUS           (0x1 << 1)
#define TIMER_ROLLOVER_INTR_STATUS        (0x1 << 2)
#define TIMER_ONCECMP_INTR_STATUS         (0x1 << 3)
#define TIMER_CYCCMP_INTR_STATUS          (0x1 << 4)
#define TACHO_CAPTURE_INTR_STATUS         (0x1 << 5)

/**
 * @name: TIMER_READ_REG32
 * @msg:  读取定时器寄存器
 * @param {u32} addr 定时器的基地址
 * @param {u32} reg_offset   定时器的寄存器的偏移
 * @return {u32} 寄存器参数
 */
#define TIMER_READ_REG32(addr, reg_offset) FtIn32(addr + (u32)reg_offset)

/**
 * @name: TIMER_WRITE_REG32
 * @msg:  写入定时器寄存器
 * @param {u32} addr 定时器的基地址
 * @param {u32} reg_offset   定时器的寄存器的偏移
 * @param {u32} reg_value    写入寄存器参数
 * @return {void}
 */
#define TIMER_WRITE_REG32(addr, reg_offset, reg_value) FtOut32(addr + (u32)reg_offset, (u32)reg_value)

#define TIMER_TIMEOUT 3000
#define TIMER_BASE_ADDR(pCtrl) TIMER_TACHO_BASE_ADDR((pCtrl)->Config.Id)
#define TIMER_CTRL_READ(pCtrl) TIMER_READ_REG32(TIMER_BASE_ADDR(pCtrl), TIMER_CTRL_REG_OFFSET)
#define TIMER_CTRL_WRITE(pCtrl, regVal) TIMER_WRITE_REG32(TIMER_BASE_ADDR(pCtrl), TIMER_CTRL_REG_OFFSET, (regVal))
#define TIMER_CMPL_READ(pCtrl) TIMER_READ_REG32(TIMER_BASE_ADDR(pCtrl), TIMER_COMP_VALL_OFFSET)
#define TIMER_CMPL_WRITE(pCtrl, cmpL) TIMER_WRITE_REG32(TIMER_BASE_ADDR(pCtrl), TIMER_COMP_VALL_OFFSET, (cmpL))
#define TIMER_CMPU_READ(pCtrl) TIMER_READ_REG32(TIMER_BASE_ADDR(pCtrl), TIMER_COMP_VALU_OFFSET)
#define TIMER_CMPU_WRITE(pCtrl, cmpU) TIMER_WRITE_REG32(TIMER_BASE_ADDR(pCtrl), TIMER_COMP_VALU_OFFSET, (cmpU))
#define TIMER_STAR_WRITE(pCtrl, cnt) TIMER_WRITE_REG32(TIMER_BASE_ADDR(pCtrl), TIMER_START_VAL_OFFSET, (cnt))
#define TIMER_STAR_READ(pCtrl) TIMER_READ_REG32(TIMER_BASE_ADDR(pCtrl), TIMER_START_VAL_OFFSET)
#define TIMER_CNTL_READ(pCtrl) TIMER_READ_REG32(TIMER_BASE_ADDR(pCtrl), TIMER_CNT_VALL_OFFSET)
#define TIMER_CNTU_READ(pCtrl) TIMER_READ_REG32(TIMER_BASE_ADDR(pCtrl), TIMER_CNT_VALU_OFFSET)
#define TACHO_RESU_READ(pCtrl) TIMER_READ_REG32(TIMER_BASE_ADDR(pCtrl), TACHO_VALL_REG_OFFSET)
#define TACHO_OVER_WRITE(pCtrl, over)  TIMER_WRITE_REG32(TIMER_BASE_ADDR(pCtrl), TACHO_OVER_LIM_OFFSET, (over))
#define TACHO_UNDER_WRITE(pCtrl, under) TIMER_WRITE_REG32(TIMER_BASE_ADDR(pCtrl), TACHO_UNDER_LIM_OFFSET, (under))

#define TIMER_INTR_M_READ(pCtrl) TIMER_READ_REG32(TIMER_BASE_ADDR(pCtrl), TIMER_INTR_MASK_OFFSET)
#define TIMER_INTR_M_WRITE(pCtrl, mask) TIMER_WRITE_REG32(TIMER_BASE_ADDR(pCtrl), TIMER_INTR_MASK_OFFSET, (mask)) 
#define TIMER_INTR_S_READ(pCtrl) TIMER_READ_REG32(TIMER_BASE_ADDR(pCtrl), TIMER_INTR_STATUS_OFFSET)
/* write 1 clear */
#define TIMER_INTR_S_CLEAR(pCtrl, status) TIMER_WRITE_REG32(TIMER_BASE_ADDR(pCtrl), TIMER_INTR_STATUS_OFFSET, (status)) 


#ifdef __cplusplus
}
#endif

#endif // !